package com.yya.ratelimiter.aspect;

import com.yya.ratelimiter.config.RedisConfig;
import com.yya.ratelimiter.enums.LimitationAlgorithmType;
import com.yya.ratelimiter.service.CounterWindow;
import com.yya.ratelimiter.service.LimitationAlgorithm;
import com.yya.ratelimiter.annotation.RateLimit;
import com.yya.ratelimiter.exception.RateLimitException;
import com.yya.ratelimiter.factory.AlgorithmFactory;
import com.yya.ratelimiter.service.TokenBucket;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebApplicationContext;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * @Autor: yuanyongan
 * @Description: 通过切片对接口实现限流操作
 * @Date 2023/1/10 14:33
 */
@Aspect
@Component
@Slf4j
public class RateLimitAspect {

    @Resource
    AlgorithmFactory algorithmFactory;

    @Resource
    CounterWindow counterWindow;

    @Resource
    TokenBucket tokenBucket;

    @Pointcut("@annotation(com.yya.ratelimiter.annotation.RateLimit)")
    public void pointCut(){}

    @Before("pointCut()")
    public void beforeRateLimit(JoinPoint jp){

        // 获取RateLimiter注解上的值
        MethodSignature methodSignature = (MethodSignature) jp.getSignature();
        RateLimit rateLimit = AnnotationUtils.findAnnotation(methodSignature.getMethod(), RateLimit.class);
        assert rateLimit != null;


        LimitationAlgorithm algorithm = algorithmFactory.getAlgorithm(rateLimit.algorithm());

        // 不通过的话直接抛出异常返回，通过的话就不做操作
        algorithm.acquire(rateLimit, methodSignature);

        algorithm.logInfo();

    }


}
